package com.tianyu.inspection.common.model;

import com.tianyu.inspection.common.component.AppConstants;
import io.lettuce.core.RedisCommandExecutionException;
import io.lettuce.core.RedisCommandTimeoutException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
import redis.clients.jedis.exceptions.JedisConnectionException;

import javax.annotation.Resource;
import java.util.List;
import java.util.Objects;
import java.util.Set;

/**********************************
 * @Author YSW
 * @Description
 * @Date 2020.12.24 - 10:34
 **********************************/

@Slf4j
@Component
public class JedisModel {

	@Resource
	private AppConstants appConstants;

	private Integer database;
	public JedisPool jedisPool;

	public void init(){
		String host = appConstants.redisHost;
		String password = appConstants.redisPassword;
		if (password == null){
			password = "";
		}
		Integer port = appConstants.redisPort;
		int timeout = Integer.parseInt(appConstants.redisTimeout.substring(0, appConstants.redisTimeout.length() - 2));
		database = appConstants.redisDatabase;
		jedisPool = new JedisPool(new JedisPoolConfig(), host, port, timeout, password);
	}

	private Jedis getJedis(){
		Jedis jedis = null;
		try{
			jedis = jedisPool.getResource();
			jedis.select(database);
		} catch (JedisConnectionException e){
			log.error("Jedis Connection timed out!");
		} catch (RedisCommandTimeoutException e){
			log.error("Jedis Command timed out!");
		} catch (RedisCommandExecutionException e){
			log.error("Jedis Command Execution timed out!");
		}
		return jedis;
	}

	public boolean set(String key, String value){
		Jedis jedis = getJedis();
		String result = "";
		if (Objects.nonNull(jedis)){
			try {
				result = jedis.set(key, value);
			} catch (JedisConnectionException e){
				log.error("Jedis Connection timed out!");
			} catch (RedisCommandTimeoutException e){
				log.error("Jedis Command timed out!");
			} catch (RedisCommandExecutionException e){
				log.error("Jedis Command Execution timed out!");
			} finally {
				jedis.close();
			}
			return "OK".equals(result);
		}
		return false;
	}

	public boolean hset(String key,String field, String value){
		Jedis jedis = getJedis();
		Long result = 0L;
		if (Objects.nonNull(jedis)){
			try {
				result = jedis.hset(key, field, value);
			} catch (JedisConnectionException e){
				log.error("Jedis Connection timed out!");
			} catch (RedisCommandTimeoutException e){
				log.error("Jedis Command timed out!");
			} catch (RedisCommandExecutionException e){
				log.error("Jedis Command Execution timed out!");
			} finally {
				jedis.close();
			}
			return 1 == result;
		}
		return false;
	}

	public String get(String key){
		Jedis jedis = getJedis();
		String result;
		if (Objects.nonNull(jedis)){
			try {
				result = jedis.get(key);
			} finally {
				jedis.close();
			}
			return result;
		}
		return null;
	}

	public String firstKey(String key){
		Jedis jedis = getJedis();
		Set<String> result;
		if (Objects.nonNull(jedis)){
			try {
				result = jedis.keys(key);
			} finally {
				jedis.close();
			}
			return result.iterator().next();
		}
		return null;
	}

	public Long llen(String key){
		Jedis jedis = getJedis();
		Long result;
		try {
			result = jedis.llen(key);
		} finally {
			jedis.close();
		}
		return result;
	}

	public Long lpush(String key,byte[] bytes){
		Jedis jedis = getJedis();
		Long result;
		try {
			result = jedis.lpush(key.getBytes(),bytes);
		}finally {
			jedis.close();
		}
		return result;
	}

	public Long rpush(String key,byte[] bytes){
		Jedis jedis = getJedis();
		Long result = null;
		try {
			result = jedis.rpush(key.getBytes(),bytes);
		} catch (JedisConnectionException e){
			log.error("Jedis Connection timed out!");
		} finally{
			jedis.close();
		}
		return result;
	}

	public List<byte[]> lrange(String key, long start, long stop){
		Jedis jedis = getJedis();
		List<byte[]> list;
		try {
			list = jedis.lrange(key.getBytes(),start,stop);
		}finally {
			jedis.close();
		}
		return list;
	}

	public Long del(String key){
		Jedis jedis = getJedis();
		Long result;
		try {
			result = jedis.del(key);
		}finally {
			jedis.close();
		}
		return result;
	}

	public void operator(RedisOperator redisOperator){
		Jedis jedis = getJedis();
		try {
			redisOperator.operator(jedis);
		}finally {
			jedis.close();
		}
	}

	public interface RedisOperator {
		void operator(Jedis jedis);
	}
}
